#pragma once

#include "../umlmodel_global.h"

#include <memory>
#include <vector>

#include "StructuredActivityNode.h"

using std::make_shared;
using std::shared_ptr;
using std::vector;

namespace uml {
class Action;
class Clause;
class OutputPin;

/// <summary>
/// ConditionalNode
/// A ConditionalNode is a StructuredActivityNode that chooses one among some number
/// of alternative collections of ExecutableNodes to execute.
/// </summary>
class UMLMODEL_EXPORT ConditionalNode : public StructuredActivityNode {

public: // Constructors and destructors
    explicit ConditionalNode(const QString& umlType="uml::ConditionalNode");

public: // JsonSerializable override
    void fromJson(const QJsonObject& json, QStringList& errorList) override;
    void toJson(QJsonObject& json) override;

public: // Methods
    /// <summary>
    /// allActions
    /// Return only this ConditionalNode. This prevents Actions within the
    /// ConditionalNode from having their OutputPins used as bodyOutputs or decider Pins
    /// in containing LoopNodes or ConditionalNodes.
    /// </summary>
    shared_ptr<vector<Action>> allActions() const override;

public: // Properties
    /// <summary>
    /// clauses getter
    /// The set of Clauses composing the ConditionalNode.
    /// </summary>
    vector<shared_ptr<Clause>>& clauses();

    /// <summary>
    /// isAssured getter
    /// If true, the modeler asserts that the test for at least one Clause of the
    /// ConditionalNode will succeed.
    /// </summary>
    bool isAssured() const;

    /// <summary>
    /// isAssured setter
    /// If true, the modeler asserts that the test for at least one Clause of the
    /// ConditionalNode will succeed.
    /// </summary>
    void setIsAssured(bool value);

    /// <summary>
    /// isDeterminate getter
    /// If true, the modeler asserts that the test for at most one Clause of the
    /// ConditionalNode will succeed.
    /// </summary>
    bool isDeterminate() const;

    /// <summary>
    /// isDeterminate setter
    /// If true, the modeler asserts that the test for at most one Clause of the
    /// ConditionalNode will succeed.
    /// </summary>
    void setIsDeterminate(bool value);

    /// <summary>
    /// results getter
    /// The OutputPins that onto which are moved values from the bodyOutputs of the
    /// Clause selected for execution.
    /// </summary>
    vector<shared_ptr<OutputPin>>& results();

private: // Fields
    /// <summary>
    /// clauses
    /// The set of Clauses composing the ConditionalNode.
    /// </summary>
    vector<shared_ptr<Clause>> clauses_;

    /// <summary>
    /// isAssured
    /// If true, the modeler asserts that the test for at least one Clause of the
    /// ConditionalNode will succeed.
    /// </summary>
    const static bool isAssured_default_;
    bool isAssured_= isAssured_default_;

    /// <summary>
    /// isDeterminate
    /// If true, the modeler asserts that the test for at most one Clause of the
    /// ConditionalNode will succeed.
    /// </summary>
    const static bool isDeterminate_default_;
    bool isDeterminate_= isDeterminate_default_;

    /// <summary>
    /// results
    /// The OutputPins that onto which are moved values from the bodyOutputs of the
    /// Clause selected for execution.
    /// </summary>
    vector<shared_ptr<OutputPin>> results_;

};

} // namespace uml
